package iface;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Handles sending messages to the server
 * @author Jeff
 *
 */
public class MessageInterface {

    /**
     * Sends an envelope to the server
     * @param env the envelope to send
     * @return a Status indicating success or failure
     */
    public static Status sendEnvelopeToServer(Envelope env) {
        Status errorStatus = new Status(Status.Result.ERROR,
                Message.MsgType.UNKNOWN);
        Socket clientSocket;
        try {
			clientSocket = new Socket();
			clientSocket.connect(NetworkConstants.SERVER_SOCKET, NetworkConstants.DEFAULT_RECV_TIMEOUT);
        } catch (UnknownHostException e) {
            errorStatus.setMessage(e.getMessage());
            return errorStatus;
        } catch (IOException e) {
            errorStatus.setMessage("Unable to create client socket: "
                    + e.getMessage());
            return errorStatus;
        }

        ObjectOutputStream outStream;
        ObjectInputStream inStream;
        try {
            outStream = new ObjectOutputStream(clientSocket.getOutputStream());
            inStream = new ObjectInputStream(clientSocket.getInputStream());
            outStream.writeObject(env);
            outStream.flush();
        } catch (IOException e) {
            errorStatus.setMessage("Unable to create in/out stream(s): "
                    + e.getMessage());
            return errorStatus;
        }

        Envelope recvEnv;
        try {
            recvEnv = recvEnvelope(inStream);
        } catch (IOException e) {
            errorStatus.setMessage("Unable to recveive response: "
                    + e.getMessage());
            return errorStatus;
        } catch (ClassNotFoundException e) {
            errorStatus.setMessage("Unable to recveive response Envelope: "
                    + e.getMessage());
            return errorStatus;
        }

        Status retStatus;
        if (recvEnv.getContents() instanceof Status) {
            retStatus = (Status) recvEnv.getContents();
        } else {
            errorStatus
                    .setMessage("Envelope does not contain a Status, this is a problem.");
            retStatus = errorStatus;
        }

        if (outStream != null && inStream != null) {
            try {
                outStream.close();
                inStream.close();
            } catch (IOException e) {
                // We can ignore this, we already have what we want!
            }
        }

        try {
            clientSocket.close();
        } catch (IOException e) {
            // We can ignore this, we already have what we want!
        }
        return retStatus;
    }

    /**
     * Receives envelopes
     * 
     * @param inStream
     *            the stream to read from
     * @return the envelope received
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static Envelope recvEnvelope(ObjectInputStream inStream)
            throws IOException, ClassNotFoundException {
        Object recvObj = inStream.readObject();
        if (recvObj instanceof Envelope) {
            Envelope env = (Envelope) recvObj;
            return env;
        } else {
            Logger.error("Unable to parse incoming object as Envelope.");
            return null;
        }
    }
}
